package products

import (
	"context"
	"devops-super/api"
	v1 "devops-super/api/product/v1"
	"devops-super/internal/consts/cacheConsts"
	"devops-super/internal/dao"
	"devops-super/internal/model/entity"
	"devops-super/internal/model/mymodel"
	"devops-super/internal/service"
	"devops-super/internal/validates"
	"errors"
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/os/glog"
	"time"
)

type sProduct struct{}

var cols = dao.AppProduct.Columns()

func init() {
	service.RegisterProduct(New())
}

func New() *sProduct {
	return &sProduct{}
}

// Add 添加产品
func (*sProduct) Add(ctx context.Context, in *entity.AppProduct) (err error) {
	vres := validates.ValidateProductKey(in.ProductKey)
	if !vres {
		err = errors.New("product key is invalid")
		return
	}
	count, _ := dao.AppProduct.Ctx(ctx).Where(cols.Name, in.Name).Count()
	if count > 0 {
		return errors.New("product already exists")
	}

	count1, _ := dao.AppProduct.Ctx(ctx).Where(cols.ProductKey, in.ProductKey).Count()
	if count1 > 0 {
		return errors.New("productKey already exists")
	}

	_, err = dao.AppProduct.Ctx(ctx).Insert(in)
	return
}

// Upt 更新产品
func (*sProduct) Upt(ctx context.Context, in *entity.AppProduct) (err error) {
	vres := validates.ValidateProductKey(in.ProductKey)
	if !vres {
		err = errors.New("product key is invalid")
		return
	}
	count, _ := dao.AppProduct.Ctx(ctx).Where(cols.Name, in.Name).Where(cols.Id+" != ", in.Id).Count()
	if count > 0 {
		return errors.New("product already exists")
	}
	count1, _ := dao.AppProduct.Ctx(ctx).Where(cols.ProductKey, in.ProductKey).Where(cols.Id+" != ", in.Id).Count()
	if count1 > 0 {
		return errors.New("productKey already exists")
	}
	_, err = dao.AppProduct.Ctx(ctx).WherePri(in.Id).OmitNilData().Data(in).Update()
	// 删除原本的缓存
	cacheKey := cacheConsts.GetProductInfoKey(int64(in.Id))
	_, _ = service.GetCacheInstance().Remove(ctx, cacheKey)
	return
}

// GetPageLst 分页获取产品列表
func (*sProduct) GetPageLst(ctx context.Context, req *v1.GetPageLstReq) (out *api.PageLstRes[*mymodel.AppProductResponse], err error) {
	out = &api.PageLstRes[*mymodel.AppProductResponse]{}
	m := dao.AppProduct.Ctx(ctx).Safe(true)

	// 状态筛选
	if req.OpenStatus != "" {
		m = m.Where(cols.OpenStatus, req.OpenStatus)
	}

	// 类型筛选
	if req.Type != "" {
		m = m.Where(cols.Type, req.Type)
	}

	// 产品名称模糊查询
	if req.Name != "" {
		m = m.Where(cols.Name+" like ? ", "%"+req.Name+"%")
	}

	// ProductKey模糊查询
	if req.ProductKey != "" {
		m = m.Where(cols.ProductKey+" like ? ", "%"+req.ProductKey+"%")
	}

	// 按时间范围筛选
	if req.TimeRange != nil {
		if len(req.TimeRange) != 2 {
			return nil, gerror.NewCode(gcode.CodeInvalidParameter, "时间范围参数格式错误")
		}
		// 新增时间转换逻辑
		startTime, err := time.Parse(time.RFC3339, req.TimeRange[0])
		if err != nil {
			return nil, gerror.WrapCode(gcode.CodeInvalidParameter, err, "开始时间格式错误")
		}
		endTime, err := time.Parse(time.RFC3339, req.TimeRange[1])
		if err != nil {
			return nil, gerror.WrapCode(gcode.CodeInvalidParameter, err, "结束时间格式错误")
		}
		timeLayout := "2006-01-02 15:04:05"
		timeStr0 := startTime.Local().Format(timeLayout)
		timeStr1 := endTime.Local().Format(timeLayout)
		m = m.WhereBetween(cols.CreatedAt, timeStr0, timeStr1)
	}

	// 分页查询原始实体
	var entities []*entity.AppProduct
	if err = m.Offset(req.Offset()).Limit(req.Limit()).ScanAndCount(&entities, &out.Total, false); err != nil {
		return
	}

	// 转换为响应模型
	out.List = make([]*mymodel.AppProductResponse, len(entities))
	for i, e := range entities {
		// 基础字段映射
		out.List[i] = &mymodel.AppProductResponse{
			Id:                  e.Id,
			Name:                e.Name,
			ProductKey:          e.ProductKey,
			Type:                e.Type,
			Description:         e.Description,
			Remark:              e.Remark,
			Image:               e.Image,
			CreatedAt:           e.CreatedAt,
			UpdatedAt:           e.UpdatedAt,
			Version:             e.Version,
			OpenStatus:          e.OpenStatus,
			OpenStatusTime:      e.OpenStatusTime,
			JointNetworkType:    e.JointNetworkType,
			TransmisionDataType: e.TransmisionDataType,
		}
	}
	return
}

// UptStatus 更新产品状态
func (*sProduct) UptStatus(ctx context.Context, id int, status int) (err error) {
	_, err = dao.AppProduct.Ctx(ctx).WherePri(id).Data(cols.OpenStatus, status).Update()
	return
}

// Del 删除产品
func (*sProduct) Del(ctx context.Context, id int) (err error) {
	// 验证产品有没有被使用
	deviceCount, _ := dao.AppDevice.Ctx(ctx).Where(dao.AppDevice.Columns().ProductId, id).Count()
	if deviceCount > 0 {
		return errors.New("cannot delete product before taken device has been deleted")
	}
	_, err = dao.AppProduct.Ctx(ctx).WherePri(id).Delete()

	// 删除缓存
	if err == nil {
		cacheKey := cacheConsts.GetProductInfoKey(int64(id))
		_, _ = service.GetCacheInstance().Remove(ctx, cacheKey)
	}

	return
}

func (*sProduct) GetOne(ctx context.Context, id int) (out *entity.AppProduct, err error) {
	out = new(entity.AppProduct)
	err = dao.AppProduct.Ctx(ctx).WherePri(id).Scan(&out)
	return
}

// GetByProductId 根据产品id获取产品信息 通过缓存获取
func (*sProduct) GetByProductId(ctx context.Context, productId int64) (out *entity.AppProduct, err error) {
	cacheKey := cacheConsts.GetProductInfoKey(productId)
	// 先从缓存获取
	if v, _ := service.GetCacheInstance().Get(ctx, cacheKey); !v.IsEmpty() {
		out = &entity.AppProduct{}
		if err = v.Struct(out); err == nil {
			return out, nil
		}
	}
	// 缓存未命中则查询数据库
	out = &entity.AppProduct{}
	err = dao.AppProduct.Ctx(ctx).Where(dao.AppProduct.Columns().Id, productId).Scan(out)
	if err != nil {
		return nil, err
	}
	// 设置缓存
	_ = service.GetCacheInstance().Set(ctx, cacheKey, out, 0)
	return out, nil
}

func (*sProduct) GetOptions(ctx context.Context, in *v1.GetOptionsReq) (out *v1.GetOptionsRes, err error) {
	out = new(v1.GetOptionsRes)
	var data []*entity.AppProduct
	err = dao.AppProduct.Ctx(ctx).Where(cols.OpenStatus, 1).Scan(&data)
	if err != nil {
		glog.Line().Error(ctx, err)
		return
	}
	out.Options = make([]*api.FormOptionsItem, 0)
	if data != nil {
		for _, v := range data {
			out.Options = append(out.Options, &api.FormOptionsItem{
				Value: v.Id,
				Label: v.Name,
			})
		}
	}
	return
}
